/*
 *  Project     : QKeyboardStatistic
 *  Author      : Durachenko Aleksey V. <durachenko.aleksey@gmail.com>, 2011
 *  Licence     : GNU GENERAL PUBLIC LICENSE Version 2
 */
#include "chookthread.h"

#include <QCoreApplication>
#include <QKeyEvent>
#include <QDebug>

// initialization of static members
QObject *CHookThread::mEventProcessor = 0;


// ----------------------------------------------------------------------
CHookThread::CHookThread(bool spyKeyboard, bool spyMouse, QObject* eventProcessor, QObject* parent)
    : QObject(parent)
{
    mEventProcessor = eventProcessor;

#ifdef WIN32
    // install windows hooks
    HINSTANCE appInstance = GetModuleHandle(NULL);
    mKeyHook = 0;
    mMouseHook = 0;
    if (spyKeyboard)
        mKeyHook = SetWindowsHookEx(WH_KEYBOARD_LL, CHookThread::LLKeyboardProcWrapper, appInstance, 0);
    if (spyMouse)
        mMouseHook = SetWindowsHookEx(WH_MOUSE_LL, CHookThread::LLMouseProcWrapper, appInstance, 0);
#else
#warning the current platform not supported
#endif
}


// ----------------------------------------------------------------------
CHookThread::~CHookThread()
{
#ifdef WIN32
    if (mKeyHook)
        UnhookWindowsHookEx(mKeyHook);
    if (mMouseHook)
        UnhookWindowsHookEx(mMouseHook);
#else
#warning the current platform not supported
#endif
}


#ifdef WIN32
// ----------------------------------------------------------------------
LRESULT CALLBACK CHookThread::LLKeyboardProcWrapper(int nCode, WPARAM wParam, LPARAM lParam)
{
    KBDLLHOOKSTRUCT *pKeyBoard = (KBDLLHOOKSTRUCT *)lParam;

    switch (wParam)
    {
    case WM_KEYDOWN:
        QCoreApplication::postEvent(mEventProcessor, new QKeyEvent((QEvent::Type)G_KeyPressEventId, pKeyBoard->vkCode, Qt::NoModifier));
        break;
    default:
        return CallNextHookEx(NULL, nCode, wParam, lParam);
    }

    return 0;
}


// ----------------------------------------------------------------------
LRESULT CALLBACK CHookThread::LLMouseProcWrapper(int nCode, WPARAM wParam, LPARAM lParam)
{
    MSLLHOOKSTRUCT *pMouse = (MSLLHOOKSTRUCT*)lParam;
    QPoint point(pMouse->pt.x, pMouse->pt.y);

    switch (wParam)
    {
    case WM_LBUTTONDOWN:
        QCoreApplication::postEvent(mEventProcessor, new QMouseEvent((QEvent::Type)G_MousePressEventId, point, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier));
        break;
    case WM_RBUTTONDOWN:
        QCoreApplication::postEvent(mEventProcessor, new QMouseEvent((QEvent::Type)G_MousePressEventId, point, Qt::RightButton, Qt::RightButton, Qt::NoModifier));
        break;
    case WM_MOUSEMOVE:
        QCoreApplication::postEvent(mEventProcessor, new QMouseEvent((QEvent::Type)G_MouseMoveEventId, point, Qt::NoButton, Qt::NoButton, Qt::NoModifier));
        break;
    default:
        return CallNextHookEx(NULL, nCode, wParam, lParam);
    }

    return 0;
}
#else
#warning the current platform not supported
#endif
